package org.java.vm;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

/**
 *
 * @author chenyang
 */
public class VMTranslator {

    public static void main(String[] args) throws IOException, URISyntaxException {
        File vmFile = createVMFileByName(args[0]);
        translate(Arrays.asList(vmFile), createDefaultAsmFile(vmFile));
    }

    public static void translate(List<File> vmFiles, File asmFile) throws IOException {
        CodeWriter codeWriter = new CodeWriter(asmFile);
        if (vmFiles.size() > 1) {
            codeWriter.writeInit();
        }

        for (File vmFile : vmFiles) {
            Parser parser = new Parser(vmFile);
            codeWriter.setFileName(vmFile.getName());
            parseAndCodeAsm(parser, codeWriter);
        }

        codeWriter.close();
    }

    private static void parseAndCodeAsm(Parser parser, CodeWriter codeWriter) throws IOException {
        while (parser.hasMoreCommand()) {
            parser.advance();
            CommandType commandType = parser.commandType();
            String arg1 = parser.arg1();
            if (commandType == CommandType.C_PUSH
                    || commandType == CommandType.C_POP) {
                Integer arg2 = parser.arg2();
                codeWriter.writePushPop(commandType, arg1, arg2);
            } else if (commandType == CommandType.C_LABEL) {
                codeWriter.writeLabel(arg1);
            } else if (commandType == CommandType.C_IF) {
                codeWriter.writeIf(arg1);
            } else if (commandType == CommandType.C_GOTO) {
                codeWriter.writeGoto(arg1);
            } else if (commandType == CommandType.C_FUNCTION) {
                Integer arg2 = parser.arg2();
                codeWriter.writeFunction(arg1, arg2);
            } else if (commandType == CommandType.C_RETURN) {
                codeWriter.writeReturn();
            } else if (commandType == CommandType.C_CALL) {
                Integer arg2 = parser.arg2();
                codeWriter.writeCall(arg1, arg2);
            } else {
                codeWriter.writeArithmetic(arg1);
            }
        }
    }

    public static File createVMFileByName(String fileName) throws URISyntaxException {
        return Paths.get(VMTranslator.class.getResource("/" + fileName).toURI()).toFile();
    }

    public static File createDefaultAsmFile(File vmFile) {
        String binFileName = vmFile.getName().replace("vm", "asm");
        return vmFile.toPath().resolveSibling(binFileName).toFile();
    }

    public static File creatAsmFile(File vmFile, String asmFileName) {
        return vmFile.toPath().resolveSibling(asmFileName).toFile();
    }
}
